package com.seecen.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.seecen.pojo.entity.Message;
import com.seecen.pojo.entity.Tally;
import com.seecen.pojo.entity.User;
import com.seecen.service.CheckinService;
import com.seecen.service.MessageService;
import com.seecen.service.TallyService;
import com.seecen.service.UserService;
import com.seecen.mapper.UserMapper;
import com.seecen.utils.JwtHelper;
import com.seecen.utils.MD5Utils;
import com.seecen.utils.Result;
import com.seecen.utils.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author xuxin
* @description 针对表【t_user(用户信息表)】的数据库操作Service实现
* @createDate 2025-10-16 10:19:26
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private JwtHelper jwtHelper;

    @Autowired
    private TallyService tallyService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private CheckinService checkinService;

    @Override
    public Result login(User user) {
        // 检查密码是否为空
        if (ObjectUtil.isEmpty(user.getPassword()) || user.getPassword().isEmpty()) {
            log.info("登录失败，密码为空");
            return Result.build(null, ResultCode.PASSWORD_ERROR);
        }

        // 使用 OR 条件一次性查询用户（支持用户名或手机号登录）
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        
        // 如果提供了用户名，添加用户名查询条件
        if (!ObjectUtil.isEmpty(user.getUsername()) && !user.getUsername().isEmpty()) {
            wrapper.eq(User::getUsername, user.getUsername());
        }
        
        // 如果提供了手机号，添加手机号查询条件（使用OR连接）
        if (!ObjectUtil.isEmpty(user.getMobile()) && !user.getMobile().isEmpty()) {
            wrapper.or().eq(User::getMobile, user.getMobile());
        }
        
        // 检查是否提供了用户名或手机号
        if (ObjectUtil.isEmpty(user.getUsername()) && ObjectUtil.isEmpty(user.getMobile())) {
            log.info("登录失败，用户名和手机号都为空");
            return Result.build(null, ResultCode.USERNAME_ERROR);
        }

        // 查询用户
        User loginUser = userMapper.selectOne(wrapper);

        // 用户不存在
        if (loginUser == null) {
            log.info("登录失败，用户不存在 - 用户名: {}, 手机号: {}", 
                    user.getUsername(), user.getMobile());
            return Result.build(null, ResultCode.USERNAME_ERROR);
        }

        // 验证密码
        String encryptedPassword = MD5Utils.encrypt(user.getPassword());
        if (!encryptedPassword.equals(loginUser.getPassword())) {
            log.info("登录失败，密码错误 - 用户ID: {}", loginUser.getId());
            return Result.build(null, ResultCode.PASSWORD_ERROR);
        }

        // 登录成功，生成token
        String token = jwtHelper.createToken(Long.valueOf(loginUser.getId()));
        HashMap<String, Object> data = new HashMap<>();
        data.put("token", token);
        
        log.info("登录成功 - 用户ID: {}, 用户名: {}", 
                loginUser.getId(), loginUser.getUsername());
        
        return Result.ok(data);
    }

    @Override
    public Result getUser(String token) {
        //token是否有效
        boolean isExpiration = jwtHelper.isExpiration(token);
        if(isExpiration) return Result.build(null, ResultCode.NOTLOGIN);

        Integer userId = jwtHelper.getUserId(token).intValue();
        User user = userMapper.selectById(userId);
        user.setPassword("");
        HashMap data = new HashMap();
        data.put("User", user);
        return Result.ok(data);
    }

    @Override
    public Result register(User user) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        //判断用户在不在
        wrapper.eq(User::getUsername,user.getUsername());
        //根据传入的getUsername查找
        User existUser = userMapper.selectOne(wrapper);
        if (existUser != null){
            //说明用户已经存在
            return Result.build(null,ResultCode.USERNAME_USED);
        }
        //密码加密
        user.setPassword(MD5Utils.encrypt(user.getPassword()));

        // 记录头像URL（如果有）
        String avatarUrl = user.getAvatar();
        log.info("注册用户头像URL: {}", avatarUrl);

        //用户存入数据库
        int insert = userMapper.insert(user);
        if (insert>0){
            //注册成功
            HashMap data = new HashMap();
            // 查询刚注册的用户信息（包含生成的ID）
            User registeredUser = userMapper.selectOne(wrapper);
            // 清除密码信息
            registeredUser.setPassword("");
            // 生成token
            String token = jwtHelper.createToken(Long.valueOf(registeredUser.getId()));
            // 将用户信息和token放入返回数据
            data.put("user", registeredUser);
            data.put("token", token);
            log.info("注册成功，用户头像: {}", registeredUser.getAvatar());
            return Result.ok(data);
        }else {
            return Result.build(null,ResultCode.USERNAME_USED);
        }
    }

    @Override
    public Result resetAccount(User user) {
        // 检查用户名和密码是否为空
        if (ObjectUtil.isEmpty(user.getUsername()) || ObjectUtil.isEmpty(user.getPassword())) {
            return Result.build(null, ResultCode.PASSWORD_ERROR);
        }

        // 查找用户
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, user.getUsername());
        User existUser = userMapper.selectOne(wrapper);

        // 用户不存在
        if (ObjectUtil.isNull(existUser)) {
            log.info("重置密码失败，用户不存在: {}", user.getUsername());
            return Result.build(null, ResultCode.USERNAME_ERROR);
        }

        // 加密新密码
        String encryptedPassword = MD5Utils.encrypt(user.getPassword());
        existUser.setPassword(encryptedPassword);

        // 更新密码
        int updateResult = userMapper.updateById(existUser);

        if (updateResult > 0) {
            log.info("密码重置成功，用户名: {}", user.getUsername());
            HashMap<String, Object> data = new HashMap<>();
            data.put("message", "密码重置成功");
            return Result.ok(data);
        } else {
            log.error("密码重置失败，用户名: {}", user.getUsername());
            return Result.build(null, ResultCode.PASSWORD_ERROR);
        }
    }

    @Override
    public Result getUserStats(String token) {
        // token是否有效
        boolean isExpiration = jwtHelper.isExpiration(token);
        if(isExpiration) return Result.build(null, ResultCode.NOTLOGIN);

        Long userId = jwtHelper.getUserId(token);

        // 获取用户信息
        User user = userMapper.selectById(userId);
        if(ObjectUtil.isNull(user)) {
            return Result.build(null, ResultCode.USERNAME_ERROR);
        }

        // 查询用户的所有记账记录
        LambdaQueryWrapper<Tally> tallyWrapper = new LambdaQueryWrapper<>();
        tallyWrapper.eq(Tally::getUserId, userId)
                .eq(Tally::getIsDeleted, 0);
        List<Tally> tallyList = tallyService.list(tallyWrapper);

        // 计算记账总笔数
        int recordCount = tallyList.size();

        // 计算记账总天数（去重日期）
        Set<LocalDate> uniqueDates = tallyList.stream()
                .map(tally -> tally.getCreateTime().toInstant()
                        .atZone(ZoneId.systemDefault()).toLocalDate())
                .collect(Collectors.toSet());
        int bookkeepingDays = uniqueDates.size();

        // 计算本月收入和支出
        LocalDate now = LocalDate.now();
        int currentYear = now.getYear();
        int currentMonth = now.getMonthValue();

        double monthlyIncome = 0.0;
        double monthlyExpense = 0.0;

        for(Tally tally : tallyList) {
            LocalDate tallyDate = tally.getCreateTime().toInstant()
                    .atZone(ZoneId.systemDefault()).toLocalDate();

            if(tallyDate.getYear() == currentYear && tallyDate.getMonthValue() == currentMonth) {
                if(tally.getType() == 1) {
                    // 支出 (type = 1)
                    monthlyExpense += tally.getPrice();
                } else if(tally.getType() == 2) {
                    // 收入 (type = 2)
                    monthlyIncome += tally.getPrice();
                }
            }
        }

        // 查询未读消息数（包括：特定用户消息 + 全局消息）
        QueryWrapper<Message> messageWrapper = new QueryWrapper<>();
        messageWrapper.eq("is_deleted", 0);
        
        // 查询条件：
        // 1. users字段包含当前用户ID（针对特定用户的消息）
        // 2. users字段为NULL（全局消息）
        // 3. users字段为'ALL'（全局消息）
        messageWrapper.and(wrapper -> wrapper
            .apply("FIND_IN_SET({0}, users) > 0", userId.toString())  // 包含用户ID
            .or()
            .isNull("users")  // 全局消息（NULL）
            .or()
            .eq("users", "ALL")  // 全局消息（'ALL'）
        );
        
        int unreadMessageCount = (int) messageService.count(messageWrapper);

        // 获取打卡相关数据
        int checkinDays = checkinService.getContinuousCheckinDays(userId);
        boolean hasCheckedInToday = checkinService.hasCheckedInToday(userId);

        // 组装返回数据
        HashMap<String, Object> data = new HashMap<>();
        data.put("username", user.getNickname() != null ? user.getNickname() : user.getUsername());
        data.put("avatar", user.getAvatar());
        data.put("checkinDays", checkinDays);
        data.put("hasCheckedInToday", hasCheckedInToday);
        data.put("bookkeepingDays", bookkeepingDays);
        data.put("recordCount", recordCount);
        data.put("monthlyIncome", monthlyIncome);
        data.put("monthlyExpense", monthlyExpense);
        data.put("balance", monthlyIncome - monthlyExpense);
        data.put("unreadMessageCount", unreadMessageCount);

        return Result.ok(data);
    }

    @Override
    public Result updateUser(String token, User user) {
        // token是否有效
        boolean isExpiration = jwtHelper.isExpiration(token);
        if(isExpiration) {
            return Result.build(null, ResultCode.NOTLOGIN);
        }
        Long userId = jwtHelper.getUserId(token);
        // 获取当前用户信息
        User existUser = userMapper.selectById(userId);
        if(ObjectUtil.isNull(existUser)) {
            return Result.build(null, ResultCode.USERNAME_ERROR);
        }

        // 更新用户信息
        if(!ObjectUtil.isEmpty(user.getUsername())){
            existUser.setUsername(user.getUsername());
        }
        if(!ObjectUtil.isEmpty(user.getNickname())) {
            existUser.setNickname(user.getNickname());
        }
        if(!ObjectUtil.isEmpty(user.getEmail())) {
            existUser.setEmail(user.getEmail());
        }
        if(!ObjectUtil.isEmpty(user.getGender())) {
            existUser.setGender(user.getGender());
        }
        if(!ObjectUtil.isEmpty(user.getAvatar())) {
            existUser.setAvatar(user.getAvatar());
        }

        int updateResult = userMapper.updateById(existUser);

        if(updateResult > 0) {
            log.info("用户信息更新成功，用户ID: {}", userId);
            HashMap<String, Object> data = new HashMap<>();
            data.put("message", "更新成功");
            return Result.ok(data);
        } else {
            log.error("用户信息更新失败，用户ID: {}", userId);
            return Result.build(null, ResultCode.PASSWORD_ERROR);
        }
    }
    // 账号注销
    @Override
    public Result revokeAccount(String token) {
        // token是否有效
        boolean isExpiration = jwtHelper.isExpiration(token);
        if(isExpiration) {
            return Result.build(null, ResultCode.NOTLOGIN);
        }

        Long userId = jwtHelper.getUserId(token);

        // 获取当前用户信息
        User existUser = userMapper.selectById(userId);
        if(ObjectUtil.isNull(existUser)) {
            return Result.build(null, ResultCode.USERNAME_ERROR);
        }

        // 逻辑删除用户（设置is_deleted=1）
        // MyBatis-Plus的逻辑删除会自动处理
        int deleteResult = userMapper.deleteById(userId);

        if(deleteResult > 0) {
            log.info("账号注销成功，用户ID: {}, 用户名: {}", userId, existUser.getUsername());
            HashMap<String, Object> data = new HashMap<>();
            data.put("message", "账号注销成功");
            data.put("username", existUser.getUsername());
            return Result.ok(data);
        } else {
            log.error("账号注销失败，用户ID: {}", userId);
            return Result.build(null, ResultCode.PASSWORD_ERROR);
        }
    }
}




